/*
 * @Author: wjc
 * @Date: 2025-07-30 16:32:50
 * @LastEditors: wjc
 * @LastEditTime: 2025-10-29 16:27:59
 * @Description:
 */
import type { ComponentRecordType, GenerateMenuAndRoutesOptions } from '@nice/types'

import type { Router } from 'vue-router'

import { BasicLayout, IFrameLayout } from '#/layouts'
import { accessRoutes, baseRouteNames } from '#/router/routes'
import { useAccessStore, useUserStore } from '#/stores/modules'
import { filterAsyncRoutes } from '#/utils/router'
import { NiceForbidden } from '@nice/nice-ui'
import {
  DEFAULT_HOME_PATH,
  generateAccessible,
  LOGIN_PATH,
  startProgress,
  stopProgress,
} from '@nice/utils'

import '#/assets/styles/nprogress.scss'

async function generateAccess(options: GenerateMenuAndRoutesOptions, actions: string[]) {
  const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue')

  const layoutMap: ComponentRecordType = {
    BasicLayout,
    IFrameLayout,
  }

  const { accessibleRoutes, accessibleMenus } = await generateAccessible('frontend', {
    ...options,
    routes: filterAsyncRoutes(options.routes, actions),
    // 可以指定没有权限跳转403页面
    forbiddenComponent: NiceForbidden,
    // 如果 route.meta.menuVisibleWithForbidden = true
    layoutMap,
    pageMap,
  })

  return {
    accessibleRoutes,
    accessibleMenus,
  }
}

/**
 * 通用守卫配置
 * @param router
 */
function setupCommonGuard(router: Router) {
  // 记录已经加载的页面
  const loadedPaths = new Set<string>()

  router.beforeEach((to) => {
    to.meta.loaded = loadedPaths.has(to.path)

    // 页面加载进度条
    if (!to.meta.loaded) {
      startProgress()
    }
    return true
  })

  router.afterEach((to) => {
    // 记录页面是否加载,如果已经加载，后续的页面切换动画等效果不在重复执行

    loadedPaths.add(to.path)

    // 关闭页面加载进度条
    stopProgress()
  })
}

/**
 * 权限访问守卫配置
 * @param router
 */
function setupAccessGuard(router: Router) {
  router.beforeEach(async (to, from) => {
    const accessStore = useAccessStore()
    const userStore = useUserStore()
    // 基本路由，这些路由不需要进入权限拦截
    if (baseRouteNames.includes(to.name as string)) {
      if (to.path === LOGIN_PATH && userStore.token) {
        return decodeURIComponent(
          (to.query?.redirect as string) || userStore.userInfo?.homePath || DEFAULT_HOME_PATH
        )
      }
      return true
    }

    // accessToken 检查
    if (!userStore.token) {
      // 明确声明忽略权限访问权限，则可以访问
      if (to.meta.ignoreAccess) {
        return true
      }

      // 没有访问权限，跳转登录页面
      if (to.fullPath !== LOGIN_PATH) {
        return {
          path: LOGIN_PATH,
          // 如不需要，直接删除 query
          query:
            to.fullPath === DEFAULT_HOME_PATH ? {} : { redirect: encodeURIComponent(to.fullPath) },
          // 携带当前跳转的页面，登录后重新跳转该页面
          replace: true,
        }
      }
      return to
    }

    // 是否已经生成过动态路由
    if (accessStore.isAccessChecked) {
      return true
    }

    // 生成路由表
    // 当前登录用户拥有的角色标识列表
    const actions = await userStore.getInfo()

    // 生成菜单和路由
    const { accessibleRoutes, accessibleMenus } = await generateAccess(
      {
        roles: actions,
        router,
        // 则会在菜单中显示，但是访问会被重定向到403
        routes: accessRoutes,
      },
      actions
    )

    // 保存菜单信息和路由信息
    accessStore.setAccessRoutes(accessibleRoutes)
    accessStore.setAccessMenus(accessibleMenus)
    accessStore.setIsAccessChecked(true)
    const redirectPath = (from.query.redirect ??
      (to.path === DEFAULT_HOME_PATH
        ? userStore.userInfo?.homePath || DEFAULT_HOME_PATH
        : to.fullPath)) as string

    return {
      ...router.resolve(decodeURIComponent(redirectPath)),
      replace: true,
    }
  })
}

export function createRouterGuard(router: Router) {
  /** 通用 */
  setupCommonGuard(router)
  /** 权限访问 */
  setupAccessGuard(router)
}
